{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "tensors.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "7i1UqqIkNxAt"
      },
      "source": [
        "# Import necessary libraries\n",
        "import tensorflow as tf\n",
        "import numpy as np"
      ],
      "execution_count": 1,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I4YPHO9ba3Bc"
      },
      "source": [
        "## Tensors\n",
        "\n",
        "Tensor are multi-dimensitonal arrays that are used in Tensorflow.\n",
        "\n",
        "We use the following definition:\n",
        "\n",
        "* **Rank:** The number of dimensions that a vector has.\n",
        "\n",
        "Below, we will define different kinds of tensors and show their rank using [tf.rank](https://www.tensorflow.org/api_docs/python/tf/rank) function."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rcU8_F3fPUb5",
        "outputId": "9f9a8970-4e6b-4550-f90f-64acf7d372b4",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "tensor = tf.constant(0)\n",
        "print(\"Print constant tensor {} of rank {}\".format(tensor, tf.rank(tensor)))\n",
        "print(\"Show full tensor:\", tensor)"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Print constant tensor 0 of rank 0\n",
            "Show full tensor: tf.Tensor(0, shape=(), dtype=int32)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ahIBf6_4cRnm",
        "outputId": "b716e303-7c30-4bc5-84d0-f9e0142b710d",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# NOTE: We use .numpy() to transform tf.tensor to numpy\n",
        "tensor = tf.constant([1,2,3])\n",
        "print(\"Tensor:\", tensor)\n",
        "print(\"Rank:\", tf.rank(tensor).numpy())"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Tensor: tf.Tensor([1 2 3], shape=(3,), dtype=int32)\n",
            "Rank: 1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ss3aDmDTd-LS"
      },
      "source": [
        "### Tensor Operations"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TKX2U0Imcm7d",
        "outputId": "7ea93f1e-a98b-418d-8f9c-5f117e1405b2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "x = tf.constant([[1, 1],\n",
        "                 [1, 1]])\n",
        "y = tf.constant([[2, 4],\n",
        "                 [6, 8]])\n",
        "\n",
        "# Add two tensors\n",
        "print(tf.add(x, y), \"\\n\")\n",
        "\n",
        "# Add two tensors\n",
        "print(tf.matmul(x, y), \"\\n\")\n"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "tf.Tensor(\n",
            "[[3 5]\n",
            " [7 9]], shape=(2, 2), dtype=int32) \n",
            "\n",
            "tf.Tensor(\n",
            "[[ 8 12]\n",
            " [ 8 12]], shape=(2, 2), dtype=int32) \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BlEgQ2t2edKl"
      },
      "source": [
        "### Muti-dimentional Tensors\n",
        "\n",
        "This part is not much different compared to what we learned so far. However, it would be nice to try extracting as much information as we can from a multi-dimentional tensor.\n",
        "\n",
        "\n",
        "Let's use [tf.ones](https://www.tensorflow.org/api_docs/python/tf/ones) for our purpose here. It creates an all-one tensor."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Gdtt0e4-fDkl",
        "outputId": "c59185ab-84f1-4e02-d327-255df4cb2b1f",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# We set the shape of the tensor and the desired data type.\n",
        "tensor = tf.ones(shape = [2, 3, 6], dtype = tf.float32)\n",
        "print('Tensor:', tensor)"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Tensor: tf.Tensor(\n",
            "[[[1. 1. 1. 1. 1. 1.]\n",
            "  [1. 1. 1. 1. 1. 1.]\n",
            "  [1. 1. 1. 1. 1. 1.]]\n",
            "\n",
            " [[1. 1. 1. 1. 1. 1.]\n",
            "  [1. 1. 1. 1. 1. 1.]\n",
            "  [1. 1. 1. 1. 1. 1.]]], shape=(2, 3, 6), dtype=float32)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "c5PChFhlfXmx",
        "outputId": "15da08f5-98df-4b54-a580-f90881976b38",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(\"Tensor Rank: \", tf.rank(tensor).numpy())\n",
        "print(\"Shape: \", tensor.shape)\n",
        "print(\"Elements' type\", tensor.dtype)\n",
        "print(\"The size of the second axis:\", tensor.shape[1])\n",
        "print(\"The size of the last axis:\", tensor.shape[-1])\n",
        "print(\"Total number of elements: \", tf.size(tensor).numpy())\n",
        "print(\"How many dimensions? \", tensor.ndim)"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Tensor Rank:  3\n",
            "Shape:  (2, 3, 6)\n",
            "Elements' type <dtype: 'float32'>\n",
            "The size of the second axis: 3\n",
            "The size of the last axis: 6\n",
            "Total number of elements:  36\n",
            "How many dimensions?  3\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cnYwTBqPhW1I"
      },
      "source": [
        "### Indexing\n",
        "\n",
        "TensorFlow indexing is aligned with Python indexing. See the following examples."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "34-Tfcsnf6uG"
      },
      "source": [
        "x = tf.constant([[1, 2, 3],\n",
        "                 [4, 5, 6],\n",
        "                 [7, 8, 9]])"
      ],
      "execution_count": 7,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tNZhisXDhoLp",
        "outputId": "5a955103-8ca5-496c-bee1-8828d437491a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# All elements\n",
        "print(x[:].numpy())"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[[1 2 3]\n",
            " [4 5 6]\n",
            " [7 8 9]]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "KUghwlZ7hr10",
        "outputId": "bc6bac99-c1f7-4f16-bb53-7cea60feb1b1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# All elements of the first row\n",
        "print(x[0,:].numpy())"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1 2 3]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NSCMESaPhwnV",
        "outputId": "71ce4701-7169-4538-f535-a5f22e5b9a1d",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# First row and last column\n",
        "print(x[0,-1].numpy())"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "3\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hH8Fhi2Sh2rt",
        "outputId": "d2d85c95-df34-4cbf-cc74-f0f9214319ac",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# From second row to last and from third column to last\n",
        "print(x[1:,2:].numpy)"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "<bound method _EagerTensorBase.numpy of <tf.Tensor: shape=(2, 1), dtype=int32, numpy=\n",
            "array([[6],\n",
            "       [9]], dtype=int32)>>\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y_zEE3-7iUmu"
      },
      "source": [
        "### Data types\n",
        "\n",
        "You can change the data type of the tesnorflow tensors for your purpose. This will be done easily by [tf.cast](https://www.tensorflow.org/api_docs/python/tf/cast)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mFsqRDxAiK95",
        "outputId": "5f3aa9b1-b5c1-4fad-cd18-96e376b742d8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "original_tensor = tf.constant([1, 2, 3, 4], dtype=tf.int32)\n",
        "print('Original tensor: ', original_tensor)\n",
        "print(\"Tensor type before casting: \", original_tensor.dtype)\n",
        "\n",
        "# Casting to change dtype\n",
        "casted_tensor = tf.cast(original_tensor, dtype=tf.float32)\n",
        "print('New tensor: ', casted_tensor)\n",
        "print(\"Tensor type after casting: \", casted_tensor.dtype)"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Original tensor:  tf.Tensor([1 2 3 4], shape=(4,), dtype=int32)\n",
            "Tensor type before casting:  <dtype: 'int32'>\n",
            "New tensor:  tf.Tensor([1. 2. 3. 4.], shape=(4,), dtype=float32)\n",
            "Tensor type after casting:  <dtype: 'float32'>\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "81XDYbnxi-nx"
      },
      "source": [
        ""
      ],
      "execution_count": 12,
      "outputs": []
    }
  ]
}